/*
Designer   : Renyangang

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

	http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package device

import (
	"context"
	"fmt"
	"fpga-vboard/bitset"
	"fpga-vboard/logger"
	"fpga-vboard/pins"
	"reflect"
	"strconv"
	"strings"
)

type GlobalInfo struct {
	ClockFrequency uint64 // 时钟频率
	ResetState     bool   // 复位状态，true表示复位完成
}

var GlobalInfoInstance = &GlobalInfo{}

// 设备配置前端描述
type DevFrontendConfig struct {
	FieldName  string
	Label      string
	Type       string
	Required   bool
	Min        int
	Max        int
	Options    []string
	Filters    string
	Unit       string
	SubConfigs []*DevFrontendConfig
}

func GetDevFrontConfigs(t reflect.Type) []*DevFrontendConfig {
	configs := make([]*DevFrontendConfig, 0)
	if t.Kind() == reflect.Ptr {
		t = t.Elem()
	}
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		var cfg *DevFrontendConfig
		frontType := field.Tag.Get("type")
		if frontType != "" {
			cfg = &DevFrontendConfig{
				FieldName: field.Name,
				Type:      frontType,
				Label:     field.Tag.Get("label"),
				Required:  field.Tag.Get("required") == "true",
				Unit:      field.Tag.Get("unit"),
			}
			switch frontType {
			case "subconfig":
				{
					subConfigs := GetDevFrontConfigs(field.Type)
					cfg.SubConfigs = subConfigs
				}
			case "number":
				{
					min := field.Tag.Get("min")
					max := field.Tag.Get("max")
					minValue, err := strconv.Atoi(min)
					if err == nil {
						cfg.Min = minValue
					}
					maxValue, err := strconv.Atoi(max)
					if err == nil {
						cfg.Max = maxValue
					}
				}
			case "select":
				{
					options := field.Tag.Get("options")
					cfg.Options = strings.Split(options, ",")
				}
			case "fileInput":
				{
					cfg.Filters = field.Tag.Get("filters")
				}
			}
			configs = append(configs, cfg)
		}
	}
	return configs
}

func setDevFrontConfig(devConfig interface{}, cfgs []*DevFrontendConfig) error {
	// 检查传入的是否为指针
	val := reflect.ValueOf(devConfig)
	if val.Kind() != reflect.Ptr {
		return fmt.Errorf("devConfig must be a pointer to a struct")
	}

	// 获取指针指向的值
	val = val.Elem()
	if val.Kind() != reflect.Struct {
		return fmt.Errorf("devConfig must be a struct pointer")
	}

	for i := 0; i < val.NumField(); i++ {
		field := val.Field(i)
		fieldType := val.Type().Field(i)

		if fieldType.Anonymous && field.Type() == reflect.TypeOf(DeviceInfo{}) {
			// 找到匿名嵌套的 DeviceInfo
			deviceInfo := field
			if deviceInfo.Kind() == reflect.Struct {
				// 修改 FrontendConfig
				deviceInfo.FieldByName("FrontendConfig").Set(reflect.ValueOf(cfgs))
				return nil
			}
		}
	}

	return fmt.Errorf("no embedded DeviceInfo found in the provided struct")
}

func InitDevFrontendConfig(devConfig interface{}) {
	t := reflect.TypeOf(devConfig)
	configs := GetDevFrontConfigs(t)
	t = reflect.TypeOf(DeviceInfo{})
	baseConfigs := GetDevFrontConfigs(t)
	configs = append(configs, baseConfigs...)
	setDevFrontConfig(devConfig, configs)
}

// 设备基本信息
type DeviceInfo struct {
	Name           string
	Id             int
	TypeName       string
	Type           int
	Self           any
	IsOptional     bool
	Enable         bool
	InputPins      []*pins.PinDef
	OutputPins     []*pins.PinDef
	PinMaps        []*pins.PinMap
	FrontendConfig []*DevFrontendConfig
}

func (di *DeviceInfo) Info() *DeviceInfo {
	return di
}

func (di *DeviceInfo) GenInfo() {
	// di.Name = DEV_NAMES[di.Id]
	di.TypeName = DEV_TYPE_NAMES[di.Type]
}

func (di *DeviceInfo) MakeDevice() Device {
	var dev Device
	if !di.Enable && di.IsOptional {
		return nil
	}
	inputPins := pins.AddPins(di.Id, di.InputPins)
	outputPins := pins.AddPins(di.Id, di.OutputPins)
	switch di.Id {
	case SOC_GLOBAL_DEFAULT:
		dev = NewSocGlobal(di.Self.(*SocGlobalConfig))
	case FLASH_DEFAULT:
		dev = NewFlash(di.Self.(*FlashConfig))
	case SDRAM_DEFAULT:
		dev = NewSDRAM(di.Self.(*RamConfig))
	case RTC_DEFAULT:
		dev = NewRealTimeClock(di.Self.(*RealTimerConfig))
	case UartDiaply_DEFAULT:
		dev = NewUartDisplay(di.Self.(*UartDisplayConfig))
	case Switchs_DEFAULT:
		dev = NewSwitchButtons(di.Self.(*SwitchsConfig))
	case Leds_DEFAULT:
		dev = NewLedLights(di.Self.(*LedsConfig))
	case CPU_DEFAULT:
		cpu := NewCpu(di.Self.(*CPUConfig))
		cpu.InputPins = inputPins
		cpu.OutputPins = outputPins
		dev = cpu
	default:
		logger.FatalEvent("device id error, id: %d", di.Id)
		return nil
	}
	dev.Init()
	dev.SetSignalPins(inputPins)
	dev.SetSignalPins(outputPins)
	return dev
}

// 设备类型基类
type DeviceBase struct {
	Config    DeviceConfig
	pinBuffer map[string]*pins.SignalPin
}

func (d *DeviceBase) Info() *DeviceInfo {
	return d.Config.Info()
}

func (d *DeviceBase) Init() error {
	d.pinBuffer = make(map[string]*pins.SignalPin)
	return nil
}

func (d *DeviceBase) SetSignalPins(signalPins []*pins.SignalPin) {
	for _, signalPin := range signalPins {
		pinName, _ := strings.CutPrefix(signalPin.Name, fmt.Sprintf("%v_", d.Info().Id))
		d.pinBuffer[pinName] = signalPin
	}
}

func (d *DeviceBase) Start(ctx context.Context) error {
	return nil
}

func (d *DeviceBase) Run(ctx context.Context) {}

func (d *DeviceBase) Stop(ctx context.Context) {}

func (d *DeviceBase) GetPinBitSet(name string) *bitset.BitSet {
	if d.pinBuffer[name] == nil {
		d.pinBuffer[name] = pins.GetPin(d.Info().Id, name)
	}
	return d.pinBuffer[name].Value
}

func (d *DeviceBase) GetPinBool(name string) bool {
	return d.pinBuffer[name].Value.Test(0)
}

func (d *DeviceBase) GetPinBytes(name string) []byte {
	return d.pinBuffer[name].Value.Bytes()
}

func (d *DeviceBase) SetPinBytes(name string, value []byte) {
	d.pinBuffer[name].Value.BytesCopyFrom(value)
}

func (d *DeviceBase) SetPinBool(name string, value bool) {
	d.pinBuffer[name].Value.SetTo(0, value)
}

func (d *DeviceBase) SetPinByte(name string, value byte) {
	d.pinBuffer[name].Value.SetByteValue(0, value)
}

func (d *DeviceBase) SetPinBoolByIndex(name string, index uint, value bool) {
	d.pinBuffer[name].Value.SetTo(index, value)
}

func (d *DeviceBase) GetBinBoolByIndex(name string, index uint) bool {
	return d.pinBuffer[name].Value.Test(index)
}

// 设备实现接口
type Device interface {
	Start(ctx context.Context) error
	Run(ctx context.Context)
	Stop(ctx context.Context)
	Info() *DeviceInfo
	Init() error
	SetSignalPins(signalPins []*pins.SignalPin)
}

// 设备配置接口
type DeviceConfig interface {
	MakeDevice() Device
	Info() *DeviceInfo
	GenInfo()
}
